﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Linq;
using System.ComponentModel;
using FinPlusAssembler;
using FinPlusInterfaces;
using FinPlusCompCore;

namespace FinPlusCompQuoteEngine
{
    public class FinPlusQuoteConnection: FinPlusComponent
    {
        [State(Test = true)]
        public override bool IsValid { get; set; }

        private enum Params { QuoteSource, ReceiveAction, PublishAction, Size }
        private FinPlusMessaging _quotesMessaging;
        private IFinPlusComp _quoteAdapterConn;
        private IPod _quoteAdapter;
        private readonly string _sourceName;
        private const int _quoteExecutePublishPercent = 5, _quoteExecutePercent = 90;

        //construct
        public FinPlusQuoteConnection(string name, IFinPlusComp quoteAdapters, IFinPlusComp quotesMessaging) 
        {
            _sourceName = name;
            _quoteAdapterConn = quoteAdapters;
            _quoteAdapter = quoteAdapters.Adapter.Values.Where(f => f[Params.QuoteSource.ToString()].ToString().Equals(_sourceName)).First<IPod>();
            _quoteAdapter.Get(Params.PublishAction.ToString(), Publish_Update);
            _quotesMessaging = (FinPlusMessaging)quotesMessaging;
            _quotesMessaging.OnUpdate += Message_Update;
            IsValid = true;
        }

        //common control interface
        public override void CmdExecute(IPod command)
        {
            try
            {
                CmdCapture(command);

                switch ((Cmds)Enum.Parse(typeof(Cmds), command.Name, true))
                {
                    case Cmds.Quote: Quote(command); break;
                    case Cmds.QuoteCancel: QuoteCancel(command); break;
                    case Cmds.QuoteExecute: QuoteExecute(command); break;
                    case Cmds.QuoteAccept: QuoteAccept(command); break;
                    case Cmds.QuoteDecline: QuoteDecline(command); break;
                    case Cmds.QuotePublish: QuotePublish(command); break;
                    case Cmds.QuoteExecutePublish: QuoteExecutePublish(command); break;
                    case Cmds.QuoteCancelPublish: QuoteCancelPublish(command); break;
                    case Cmds.QuoteDeclinePublish: QuoteDeclinePublish(command); break;
                    case Cmds.QuoteAcceptPublish: QuoteAcceptPublish(command); break;
                    default: throw new QuoteEngineException(string.Format("cmd not recognised {0}", command.Name));
                }
            }
            catch (CmdExecuteException e)
            {
                IsValid = Level.Error.Log(Id, Config, e.Message, e);
            }
        }

        public override void Dispose()
        {
            try
            {
                if (_quoteAdapterConn != null)
                    _quoteAdapterConn.Dispose();
            }
            catch (Exception e)
            {
                Level.Warning.Log(e.Message, e);
            }
        }

        //quote
        private void Quote(IPod pod){ _quoteAdapter.Get(Params.ReceiveAction.ToString()).Update(pod); }

        private void QuoteCancel(IPod pod) {_quoteAdapter.Get(Params.ReceiveAction.ToString()).Update(pod); }

        private void QuoteExecute(IPod pod)
        {
            //trader trys to execute 
            if (new Random().Next(0, 100) < _quoteExecutePercent)
            {
                //route as accept
                pod.Get(PodField.Type.ToString()).Parse(pod.Name = Cmds.QuoteAccept.ToString());
                Message_Update(this, pod);
            }
            else
            {
                //route as decline
                pod.Get(PodField.Type.ToString()).Parse(pod.Name = Cmds.QuoteDecline.ToString());
                Message_Update(this, pod);
            }
        }

        private void QuoteAccept(IPod pod) { _quoteAdapter.Get(Params.ReceiveAction.ToString()).Update(pod); }

        private void QuoteDecline(IPod pod) { _quoteAdapter.Get(Params.ReceiveAction.ToString()).Update(pod);}

        private void QuotePublish(IPod pod)
        {
            if ((double)pod.Value(Params.Size.ToString()) != 0 && new Random().Next(0, 100) < _quoteExecutePublishPercent)
            {
                pod.Get(PodField.Type.ToString()).Parse(pod.Name = Cmds.QuoteExecutePublish.ToString());
                Message_Update(this, pod);
            }
        }

        private void QuoteCancelPublish(IPod pod)
        {  
            //TODO 
        }

        private void QuoteAcceptPublish(IPod pod)
        {
            //TODO
        }

        private void QuoteDeclinePublish(IPod pod)
        {
            //TODO
        }

        private void QuoteExecutePublish(IPod pod){ _quoteAdapter.Get(Params.ReceiveAction.ToString()).Update(pod);}

        //cmds
        private enum Cmds { Quote, QuoteCancel, QuoteExecute, QuoteAccept, QuoteDecline, QuotePublish, QuoteDeclinePublish, QuoteCancelPublish, QuoteAcceptPublish, QuoteExecutePublish };

        //events
        private void Message_Update(object s, IPod pod) { CmdExecute(pod); }
        private void Publish_Update(object s, PropertyChangedEventArgs a) { CmdRouter(s); }
    }
}
